1 O que é NLP?
Ensinar máquinas a entender a linguagem humana — um dos problemas mais difíceis da IA.
Por que NLP é difícil?
Ambiguidade
"Vi o homem com o telescópio" — quem tinha o telescópio?
Contexto
"Banco" pode ser instituição financeira, assento ou de dados.
Ironia/Sarcasmo
"Que dia lindo!" dito numa tempestade significa o oposto.
Variação linguística
"Tá", "tá bom", "está bem", "ok" — tudo significa a mesma coisa.
Dependência de longo alcance
"O livro que comprei ontem e li durante a viagem era..." — "era" se refere a "livro".
Morfologia
"correr", "corri", "correndo", "corredor" — mesma raiz, formas diferentes.
O que NLP resolve?
| Tarefa | Exemplo | Aplicação real |
|---|---|---|
| Classificação de texto | "Este produto é ruim" → negativo | Análise de sentimentos |
| NER | "João foi à São Paulo" → [Pessoa: João] [Local: São Paulo] | Extração de informações |
| Tradução | "Hello" → "Olá" | Google Translate |
| Sumarização | Texto de 10 páginas → resumo de 1 parágrafo | News summarization |
| QA (Pergunta-Resposta) | "Quando o contrato vence?" → "Março/2026" | Chatbots, RAG |
| Geração de texto | Prompt → texto coerente | ChatGPT, Claude |
2 Tokenização — texto vira números
O primeiro passo de qualquer modelo de linguagem: transformar texto em unidades processáveis.
Abordagens de tokenização
Por caractere
Cada caractere é um token. Vocabulário pequeno (~100), mas sequências muito longas.
Ex: "casa" → ['c', 'a', 's', 'a']
Por palavra
Cada palavra é um token. Intuitivo, mas vocabulário enorme e não lida com palavras desconhecidas (OOV).
Ex: "casa azul" → ['casa', 'azul']
Subword (BPE, WordPiece)
Mistura: palavras frequentes são tokens únicos, palavras raras são divididas em subpalavras. É o padrão moderno.
Ex: "tokenização" → ['token', 'iza', 'ção']
🎮 Simulador de Tokenização BPE
Digite um texto e veja como ele é tokenizado
Como funciona: o BPE começa com caracteres e iterativamente junta os pares mais frequentes. Palavras comuns viram tokens únicos; palavras raras são divididas. Cada token tem um ID numérico (passe o mouse para ver).
Por que subword é o padrão?
❌ Tokenização por palavra
Problema: palavras desconhecidas (OOV)
"NimbusCloud" não está no vocabulário → token <UNK>
O modelo perde informação!
✅ Tokenização subword (BPE)
Solução: divide em subpalavras conhecidas
"NimbusCloud" → ["Nimbus", "Cloud"]
O modelo ainda entende!
Código Python: tokenização com Hugging Face
from transformers import AutoTokenizer # Carrega tokenizador do GPT-2 (BPE) tokenizer = AutoTokenizer.from_pretrained("gpt2") # Tokeniza um texto text = "A tokenização é fundamental para LLMs" tokens = tokenizer(text) print(f"Tokens: {tokens.tokens()}") # ['A', ' token', 'ização', ' é', ' fundamental', ' para', ' L', 'LM', 's'] print(f"IDs: {tokens['input_ids']}") # [32, 3797, 4672, 318, 16385, 3518, 40, 1842, 2] # Cada token tem um ID numérico único # Esses IDs viram a entrada da rede neural
3 Bag of Words e TF-IDF
As primeiras formas de transformar texto em números — simples, mas limitadas.
Bag of Words (BoW)
Cada documento vira um vetor onde cada posição representa uma palavra do vocabulário, e o valor é a contagem dessa palavra no documento.
# Exemplo: 3 documentos doc1 = "o gato comeu o rato" doc2 = "o rato fugiu do gato" doc3 = "o gato dormiu" # Vocabulário: [o, gato, comeu, rato, fugiu, do, dormiu] # Representação BoW: doc1_vec = [2, 1, 1, 1, 0, 0, 0] # "o" aparece 2x, "gato" 1x, etc. doc2_vec = [1, 1, 0, 1, 1, 1, 0] doc3_vec = [1, 1, 0, 0, 0, 0, 1]
O problema: palavras comuns dominam
"o", "de", "para" aparecem em quase todos os documentos — não carregam informação útil. TF-IDF resolve isso.
TF-IDF (Term Frequency - Inverse Document Frequency)
Pesa cada palavra por:
- TF: frequência da palavra no documento (quanto mais, mais importante)
- IDF: inverso da frequência nos documentos (quanto mais rara, mais importante)
TF-IDF = TF(t,d) × IDF(t)
# Onde:
TF(t,d) = contagem de t em d / total de palavras em d
IDF(t) = log(total de docs / docs que contêm t)
🎮 Simulador de TF-IDF
Veja como TF-IDF pesa palavras em diferentes documentos
3 documentos da Nimbus Cloud. Palavras raras ganham peso alto; palavras comuns (como "o", "de") ganham peso baixo.
Interpretação: palavras com barras maiores são mais "importantes" para aquele documento específico. Note como "timeout" é importante no Doc 1 e 3, mas não no Doc 2.
Código Python: TF-IDF com scikit-learn
from sklearn.feature_extraction.text import TfidfVectorizer # Documentos da Nimbus Cloud docs = [ "timeout no endpoint /v2/sync após 30 segundos", "API v3.2 documentação autenticação JWT", "runbook aumentar NIMBUS_TIMEOUT para 120 segundos" ] # Cria vetorizador TF-IDF vectorizer = TfidfVectorizer() tfidf_matrix = vectorizer.fit_transform(docs) # Mostra palavras e seus pesos feature_names = vectorizer.get_feature_names_out() for i, doc in enumerate(docs): print(f"\nDoc {i+1}: {doc}") for j in tfidf_matrix[i].nonzero()[1]: print(f" {feature_names[j]}: {tfidf_matrix[i, j]:.3f}")
Limitações de BoW e TF-IDF
✅ Vantagens
• Simples e rápido
• Funciona bem para classificação básica
• Baseline sólido
❌ Limitações
• Ignora ordem das palavras
• Não captura semântica ("gato" e "felino" são diferentes)
• Vetores esparsos (muitos zeros)
4 Word2Vec — os primeiros embeddings
A revolução de 2013: palavras viram vetores densos que capturam significado.
vetor("rei") - vetor("homem") + vetor("mulher") ≈ vetor("rainha").
Como funciona o Word2Vec
Dois algoritmos principais:
CBOW (Continuous Bag of Words)
Prediz a palavra central a partir das palavras ao redor.
Ex: "o gato [?] no sofá" → prediz "dormiu"
Skip-gram
Prediz as palavras ao redor a partir da palavra central.
Ex: "gato" → prediz "o", "dormiu", "no", "sofá"
🎮 Mapa 2D de palavras (Word2Vec)
Clique em uma palavra para ver as mais similares
Interpretação: palavras semanticamente similares estão próximas no espaço. Note como "timeout", "expiração" e "falha" formam um cluster; "contrato", "prazo" e "cláusula" formam outro.
Mais similares: -
O famoso exemplo: rei - homem + mulher = rainha
import numpy as np from gensim.models import KeyedVectors # Carrega modelo Word2Vec pré-treinado model = KeyedVectors.load_word2vec_format('word2vec-google-news-300.gz') # Analogia: rei - homem + mulher = ? result = model.most_similar( positive=['rei', 'mulher'], negative=['homem'] ) print(result[0]) # ('rainha', 0.71) ← a palavra mais próxima é "rainha"! # Outras analogias funcionam: # Paris - França + Itália = Roma # Tóquio - Japão + China = Pequim
Por que Word2Vec foi revolucionário?
❌ Antes (TF-IDF)
• Vetores esparsos (milhares de dimensões, maioria zero)
• "Gato" e "felino" = completamente diferentes
• Sem noção de semântica
✅ Depois (Word2Vec)
• Vetores densos (300 dimensões, todas preenchidas)
• "Gato" e "felino" = vetores muito próximos
• Captura semântica e relações
Limitações do Word2Vec
❌ Um vetor por palavra
"Banco" (instituição) e "banco" (assento) têm o mesmo vetor!
Não lida com polissemia (múltiplos significados).
❌ Ignora contexto da frase
"O banco faliu" e "sentei no banco" → mesma representação.
Perde informação contextual crucial.
5 RNNs e LSTMs — processando sequências
Redes neurais que lembram do passado — a base do NLP moderno antes dos Transformers.
Como funciona uma RNN
A cada passo t, a RNN:
- Recebe o input atual
x[t](token atual) - Recebe o estado oculto anterior
h[t-1](memória) - Calcula o novo estado oculto
h[t] = f(W*x[t] + U*h[t-1] + b) - Usa
h[t]para fazer previsão ou passar para o próximo passo
🎮 Visualização: RNN processando uma frase
Veja como o estado oculto evolui a cada token
Interpretação: a cada token, o estado oculto (memória) é atualizado. No final, o estado oculto contém uma "representação" de toda a frase.
O problema das RNNs: dependências de longo alcance
❌ RNN simples
Frase: "O livro que comprei ontem e li durante a viagem era..."
Quando chega em "era", a RNN já "esqueceu" que o sujeito é "livro".
Vanishing gradient: informação se perde ao longo do tempo.
✅ LSTM (Long Short-Term Memory)
Solução: portas (gates) que decidem o que lembrar e o que esquecer.
Consegue manter informação por centenas de passos.
Resolve (parcialmente) o vanishing gradient.
LSTM: as 3 portas mágicas
Forget Gate
Decide o que esquecer da memória anterior. Ex: "o sujeito mudou, posso esquecer o anterior".
Input Gate
Decide o que armazenar na memória. Ex: "essa informação é importante, vou guardar".
Output Gate
Decide o que usar da memória agora. Ex: "vou usar essa informação para a previsão atual".
Código Python: LSTM com PyTorch
import torch import torch.nn as nn class SentimentLSTM(nn.Module): def __init__(self, vocab_size, embed_dim=100, hidden_dim=128): super().__init__() self.embedding = nn.Embedding(vocab_size, embed_dim) self.lstm = nn.LSTM(embed_dim, hidden_dim, batch_first=True) self.fc = nn.Linear(hidden_dim, 1) # binary classification def forward(self, x): # x shape: (batch, seq_len) embedded = self.embedding(x) # (batch, seq_len, embed_dim) # LSTM processa a sequência output, (hidden, cell) = self.lstm(embedded) # Usa o último estado oculto para classificação out = self.fc(hidden.squeeze(0)) return torch.sigmoid(out) # Uso model = SentimentLSTM(vocab_size=10000) tokens = torch.tensor([[5, 23, 142, 87, 3]]) # sequência de tokens output = model(tokens) print(f"Sentimento: {output.item():.2f}") # 0.82 → positivo
RNNs vs LSTMs vs GRUs
| Arquitetura | Memória | Complexidade | Uso típico |
|---|---|---|---|
| RNN simples | Curto prazo (vanishing gradient) | Baixa | Raramente usada hoje |
| LSTM | Longo prazo (3 portas) | Alta | NLP clássico (2015-2018) |
| GRU | Longo prazo (2 portas) | Média | Alternativa mais leve ao LSTM |
6 O problema das dependências de longo alcance
Por que RNNs falham em frases longas — e como isso motivou os Transformers.
Exemplo prático
# Frase longa com dependência distante "O contrato que assinamos em janeiro após meses de negociação com o fornecedor e revisão jurídica finalmente foi aprovado pelo conselho e publicado no diário oficial em março e agora precisamos saber quando ele vence." # Pergunta: "quando o contrato vence?" # Resposta está em "março" — mas está a 50+ palavras de distância! # RNN/LSTM: # - Processa palavra por palavra # - Quando chega em "vence", já "esqueceu" parcialmente "março" # - Mesmo LSTM tem dificuldade com 50+ palavras # Transformer (próximo módulo): # - Conecta TODAS as palavras diretamente (self-attention) # - "vence" pode "olhar" diretamente para "março" # - Não importa a distância
Por que isso importa para RAG?
Em RAG, os chunks podem ter 300-500 tokens. Se o modelo não consegue capturar dependências de longo alcance, vai perder informação importante dentro do próprio chunk.
7 Conexão com RAG
Como tudo que você aprendeu aqui se aplica ao Módulo 7 (RAG).
Conceitos que se conectam
| Conceito de NLP | Aplicação em RAG |
|---|---|
| Tokenização | Chunks são medidos em tokens, não palavras. Tokenizadores como BPE são usados por todos os LLMs modernos. |
| TF-IDF / BM25 | Busca lexical em RAG usa BM25 (evolução do TF-IDF) para match exato de códigos, datas, IDs. |
| Word Embeddings | Evoluíram para sentence embeddings (vetores de chunks inteiros). Base da busca vetorial. |
| RNNs/LSTMs | Foram substituídas por Transformers, mas o conceito de "estado oculto" inspirou arquiteturas modernas. |
| Dependências de longo alcance | Transformers resolvem isso com self-attention, permitindo chunks maiores sem perder informação. |
Evolução do NLP até os LLMs
1990-2010
BoW, TF-IDF, SVM. Estatística clássica.
2013
Word2Vec. Palavras viram vetores densos.
2014-2017
RNNs, LSTMs, GRUs. Sequências com memória.
2017
Transformers. "Attention is All You Need".
2018
BERT, GPT. Modelos pré-treinados em larga escala.
2020-2026
GPT-3/4, Claude, Llama. LLMs que geram texto.
🎯 Quiz — teste seu conhecimento
Clique em uma alternativa para ver se acertou.
→ O que vem a seguir?
Agora que você entende NLP clássico, vamos mergulhar na arquitetura que mudou tudo.
Conceitos que vamos construir aqui
Self-Attention
Cada token "olha" para todos os outros diretamente.
Multi-Head Attention
Múltiplas "atenções" capturando diferentes relações.
Positional Encoding
Como a ordem das palavras é preservada.
Encoder vs Decoder
BERT (encoder) vs GPT (decoder).